package apt

import (
	"container/list"
	"errors"
	"fmt"

	"gitee.com/liumou_site/gbm"
	"gitee.com/liumou_site/gf"
	"gitee.com/liumou_site/logger"
	"github.com/spf13/cast"
)

// LocalInstallList 根据文件列表安装本地包
// 参数:
//
//	fileList []string: 包文件路径列表
//	name string: 包的名称
//
// 返回值:
//
//	bool: 安装是否成功
func (api *AptStruct) LocalInstallList(fileList []string, name string) bool {
	// 将切片转换为字符串
	installStr := gbm.SliceToString(fileList, " ")
	// 调用AptLocalInstallStr方法进行安装处理
	status := api.AptLocalInstallStr(installStr, name)
	// 返回处理状态
	return status
}

// AptLocalInstallStr 安装本地软件包字符串
// 参数:
//
//	installStr: 要安装的软件包字符串，包含多个软件包时以空格分隔
//	name: 软件包的名称，用于日志信息
//
// 返回值:
//
//	bool: 安装是否成功，成功返回true，否则返回false
func (api *AptStruct) AptLocalInstallStr(installStr, name string) bool {
	// 继承屏蔽设置
	api.Sudo.Ignore = api.Ignore
	api.Sudo.BlackHole = api.BlackHole

	// 执行sudo命令安装软件包
	api.Sudo.RunSudo("apt install -y -f", installStr)

	// 根据执行结果输出日志信息
	if api.Sudo.Err == nil && api.Info {
		logger.Info("[ %s ] Installation succeeded", name)
	} else {
		logger.Error("[ %s ] Installation Failed: ", name, api.Sudo.Err.Error())
	}

	// 将错误信息传递给上层
	api.Err = api.Sudo.Err

	// 根据是否有错误返回结果
	return api.Sudo.Err == nil
}

// AptLocalInstallFile 安装本地软件包文件。
// 该函数接受文件名和软件包名称作为参数，尝试使用sudo apt install命令安装指定的软件包文件。
// 参数:
//
//	filename - 要安装的软件包文件名。
//	name - 软件包的名称，用于日志信息。
//
// 返回值:
//
//	可能发生的错误。
func (api *AptStruct) AptLocalInstallFile(filename, name string) (err error) {
	// 继承屏蔽设置到Sudo对象，用于控制输出。
	api.Sudo.Ignore = api.Ignore
	api.Sudo.BlackHole = api.BlackHole

	// 创建NewFile对象以检查文件是否存在。
	f := gf.NewFile(filename)

	// 检查是否存在多个文件，此处似乎是误用，应该使用IsFile。
	f.IsFile()
	if f.IsFiles {
		// 执行sudo apt install命令安装软件包文件。
		api.Sudo.RunSudo("apt install -y -f ", filename)
		// 根据执行结果输出成功或错误日志。
		if api.Sudo.Err == nil && api.Info {
			logger.Info("[ %s ] Installation succeeded", name)
		} else {
			logger.Error("[ %s ] Installation Failed: ", name, api.Sudo.Err.Error())
		}
		// 保存可能发生的错误。
		api.Err = api.Sudo.Err
	} else {
		// 如果文件不存在，输出错误日志并返回错误。
		msg := fmt.Sprintf("fileMan does not exist: %s", filename)
		logger.Error(msg)
		api.Err = errors.New(msg)
		fmt.Println(err)
	}
	return
}

// InstallList 安装给定的软件包列表，并返回安装成功和失败的软件包列表。
//
// 参数:
//   - pacList: 包含待安装软件包的链表。
//
// 返回值:
//   - ok: 包含安装成功的软件包的链表。
//   - failed: 包含安装失败的软件包的链表。
func (api *AptStruct) InstallList(pacList list.List) (ok, failed list.List) {
	// 初始化安装成功和失败的链表
	installListOk := list.New()
	installListFailed := list.New()

	// 遍历输入的软件包列表，尝试安装每个软件包
	for i := pacList.Front(); i != nil; i = i.Next() {
		pac := fmt.Sprint(i.Value)
		un := api.Install(pac)
		if un {
			installListOk.PushBack(pac)
		} else {
			installListFailed.PushBack(pac)
		}
	}

	// 返回安装成功和失败的软件包列表
	return *installListOk, *installListFailed
}

// InstallSlice 安装一组软件包并返回安装成功和失败的软件包列表
// 参数:
//
//	pacList []string: 待安装的软件包列表
//
// 返回值:
//
//	ok list.List: 安装成功的软件包列表
//	failed list.List: 安装失败的软件包列表
func (api *AptStruct) InstallSlice(pacList []string) (ok, failed list.List) {
	// 安装成功的列表
	installListOk := list.New()
	// 安装失败的列表
	installListFailed := list.New()

	// 遍历待安装的软件包列表
	for p := range pacList {
		// 将接口类型转换为字符串类型
		pac := cast.ToString(p)
		// 调用 Install 方法安装软件包并获取安装结果
		un := api.Install(pac)
		// 根据安装结果将软件包添加到相应的列表中
		if un {
			installListOk.PushBack(pac)
		} else {
			installListFailed.PushBack(pac)
		}
	}
	// 返回安装成功和失败的软件包列表
	return *installListOk, *installListFailed
}

// Install 安装指定的软件包
// 参数:
//
//	Package: 需要安装的软件包名称
//
// 返回值:
//
//	bool: 安装是否成功
func (api *AptStruct) Install(Package string) bool {
	// 继承屏蔽设置
	api.Sudo.Ignore = api.Ignore
	// 继承屏蔽设置
	api.Sudo.BlackHole = api.BlackHole
	// 执行安装命令
	api.Sudo.RunSudo("apt install -y", Package)
	// 检查是否有错误发生
	if api.Sudo.Err == nil {
		// 如果没有错误且开启了信息输出
		if api.Info {
			// 记录安装成功的日志
			logger.Info("[ %s ] Installation succeeded", Package)
		}
	} else {
		// 输出错误信息
		fmt.Println(api.Sudo.Err)
		// 记录安装失败的日志
		logger.Error("Installation Failed")
	}
	// 将错误信息赋值给api对象的Err属性
	api.Err = api.Sudo.Err
	// 返回安装是否成功
	return api.Err == nil
}
